"""
##.. module:: FeatureExtraction

FeatureExtraction will contain logic for all feature extractions, including:

    1. Spurious events (e.g. data flat-lining)
    2. Individual loads
    3. ...

.. moduleauthor:: Joe Kwiatkowski http://joejk.com
##
"""
# Core imports:
import sys
from optparse import OptionParser
import scipy
import time


# Project imports:
#sys.path.append('../data')
#sys.path.append('..')
from .. import conf
from .. import data

"""
##.. function:: findFlatSegs

    Find flat segments.
##
"""
def findFlatSegs(data=None, minSeg=3600, sampleSeg=None,\
                 lower=None, upper=None):
    if sampleSeg==None: 
        sampleSeg = minSeq / 100
    # Doesn't make sense to look for flat segments any shorter than 2
    # data-points long:
    if sampleSeg < 2: 
        sampleSeg == 2
    # sampleSeg must be smaller than minSeg, otherwise 'pos' wouldn't be
    # incremented (see below).
    if sampleSeg > minSeg: 
        sampleDeg = minSeg - 1 

    # Read data if necessary:
    if data==None:
        data = data.readFromDB(lower, upper)

    if len(data['kW']) < sampleSeg:
        print 'Time span of data smaller than time span of spurious data'
        return

    # Store flat segments as [(min, max), (min, max), ...], where both bounds
    # are inclusive (segment is still flat at that point).
    flatSegs = []

    pos=0
    while pos < len(data['kW']) - sampleSeg:
        var = scipy.var(data['kW'][pos:pos+sampleSeg])

        if var < conf.FP_ZERO:
            minPos = pos
            maxPos = pos
            while minPos - 1 >=0 and \
                  abs(data['kW'][minPos - 1] - data['kW'][pos]) < conf.FP_ZERO:
                minPos -= 1
            while maxPos + 1 < len(data['kW']) and \
                  abs(data['kW'][maxPos + 1] - data['kW'][pos]) < conf.FP_ZERO: 
                maxPos += 1

            if maxPos - minPos > minSeg:
                flatSegs.append([minPos, maxPos])

            pos = maxPos

        else:
            pos += minSeg - sampleSeg

    return flatSegs
    
"""
##.. function:: monitorFlatSegs

Look for flat segments in the data as it is collected. Run by using
:func:`monitor`.

##
"""

class monitorFlatSegs(object):
    
    def __init__(self):
        self.dataPointsCount = 0
        self.flatSegs = []


    def run(self, data, **kwargs):
        print "get here"
        print "length of data", len(data['kW'])
        flatSegs = findFlatSegs(data=data, minSeg=kwargs['minSeg'], 
                                sampleSeg=kwargs['sampleSeg'])

        # If have both old and new flat segments...
        if len(self.flatSegs) != 0 and len(flatSegs) != 0:
            # then check if flat segment extends from previously monitored data.
            if flatSegs[0][0] == 0 and \
               self.flatSegs[-1][1] == self.dataPointsCount - 1:
            
                # If so, consolidate the two flat segments, by extending the 
                # *old* segment and deleting the new segment:
                self.flatSegs[-1][1] = flatSegs[0][1] + self.dataPointsCount
                flatSegs = flatSegs[1:] 

        # Properly number the new flat segs...
        flatSegs = [[fs1 + self.dataPointsCount, fs2 + self.dataPointsCount]\
                     for [fs1, fs2] in flatSegs]

        # ... and then add new flat segs to list:
        self.flatSegs += flatSegs

        # And increment the number of data-points read:
        self.dataPointsCount += len(data['kW'])

        print self.flatSegs


def findFlatSegsNaive(data=None, minSeg=3600, lower=None, upper=None):
    # Read data if necessary:
    if data==None:
        data = data.readFromDB(lower, upper)

    if len(data['kW']) < minSeg:
        print 'Time span of data smaller than time span of spurious data'
        return

    pos=0
    while pos < len(data['kW']) - minSeg:
        var = scipy.var(data['kW'][pos:pos+minSeg])

        if var < conf.FP_ZERO:
            print "Spurious flat-line at %s" %\
            time.strftime("%Y-%m-%d %H:%M:%S", data['dateTime'][pos])

        pos += minSeg




if __name__ == "__main__":
    # Get options and args:
    options = []
    parser = OptionParser("%prog: OPTIONS") 
    parser.add_option('--lower', help="Lower bound of dateTime", type='string',
                      default=None)
    parser.add_option('--upper', help="Upper bound of dateTime", type='string',
                      default=None)
    (opts, args) = parser.parse_args(sys.argv)

    # Run: 
    findFlatSegs(None, opts.lower, opts.upper)
